/*
 * IO.c
 *
 * Created: 26.03.2012 14:54:53
 *  Author: Luke
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "IO.h"
#include "../vs1011/vs1011e.h"
#include "../Playback.h"
#include "../sdfat-rr/uart.h"

void ioInit(void)
{
	//PORTC0..4 = input
	DDRC &= ~(_BV(PORTC0)|_BV(PORTC1)|_BV(PORTC2)|_BV(PORTC3)|_BV(PORTC4));
	//enable pull-ups on inputs
	PORTC |= _BV(PORTC0)|_BV(PORTC1)|_BV(PORTC2)|_BV(PORTC3)|_BV(PORTC4);
	
	//PORTC5 = output (self-hold) @ MSM2 Pins 12,14,16
	DDRC |= _BV(PORTC5);
	PORTC &= ~_BV(PORTC5);
	
	PCMSK1 = _BV(PCINT8)|_BV(PCINT9)|_BV(PCINT10)|_BV(PCINT11)|_BV(PCINT12);
	
	//overflow int on
	TIMSK0 = _BV(TOIE0);
	
	_delay_ms(10);
	
	startup_buttons_ = ioGetButtons();
	ioClrAndEnableISR();
	//enable external hold-power circuit
	ioSelfHoldOn();
}

void ioSelfHoldOn()
{
	PORTC |= _BV(PORTC5);
}

void ioSelfHoldOff()
{
	PORTC &= ~_BV(PORTC5);
}

void ioClrAndEnableISR()
{
	//clear Interrupt
	PCIFR = _BV(PCIF1);
	//unmask interrupt
	PCICR = _BV(PCIE1);	
}	



uint8_t ioProcessButton(uint8_t button)
{
	static uint8_t last_button_processed = 0;
	static uint8_t last_button_state = 0;
	static uint8_t max_button = 0;
/*
		//MSM2 C_KS1, pins 3,11,17:   1
		//MSM2 C_KS2, pins 5,13,19:   2
		//MSM2 C_KS3, Pins 7,15,21:   4
		//MSM2 C_KS4, pin 9:          8
		//MSM2 KS1,   pins 4,6,8,10: 16
*/
	//find max. simultaneous button presses
	if (button > last_button_state)
		max_button = button;
	
	//save for compare in next interrupt
	last_button_state = button;	
	
	//all buttons released (only first time)
	if ((button == 0) && max_button)
	{
		pbStopPlaybackAsync();
		
		//if the same button is pressed again, just stop the playback
		if (max_button == last_button_processed)
			pbSetNextSong(0);
		else
			pbSetNextSong(max_button);
	
		//reset vars
		last_button_processed = max_button;
		max_button = 0;
		
		return last_button_processed;
	}		
		
	return 0;
}

uint8_t ioGetButtons()
{
	
	return((~PINC) & 0x1F);
}

void ioFakeButton(uint8_t button)
{
	ioProcessButton(button);
	ioProcessButton(0x00);
}

void ioDelayedButtonHandler()
{
	//uart_puts_p(PSTR("GO.."));
	TCNT0 = 0;
	
	//mask interrupt
	PCICR &= ~_BV(PCIE1);	

	//clock on
	//1024 prescaler --> ~32ms runtime
	TCCR0B = _BV(CS02) | _BV(CS00);
}

ISR(PCINT1_vect)
{
	ioDelayedButtonHandler();
}	


ISR (TIMER0_OVF_vect)
{
	//uart_puts_p(PSTR("OVF\n"));
	//clock off
	TCCR0B = 0x00;
	ioProcessButton(ioGetButtons());
	ioClrAndEnableISR();
}